/*
 * ==================================================================
 *             메인 메소드 :  실행 클래스 
 * ==================================================================
 */
package kr.ac.ssu.ailab.View;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;

import kr.ac.ssu.ailab.Control.CellControl;
import kr.ac.ssu.ailab.Control.ClusterControl;
import kr.ac.ssu.ailab.Control.ClusterSearch;
import kr.ac.ssu.ailab.Control.NewHeuristicPathFinding;

import kr.ac.ssu.ailab.Control.GraphControl;
import kr.ac.ssu.ailab.Control.MapControl;

import kr.ac.ssu.ailab.Model.Data.Cell;
import kr.ac.ssu.ailab.Model.Data.Agent.Agent;
import kr.ac.ssu.ailab.Model.Data.Agent.AgentGroup;
import kr.ac.ssu.ailab.Model.Data.Agent.MSG;

/*
 1. Map 생성(Cell 은 Map 생성자 안에서 생성된다.
 2. 클러스터 구성하고 
 3. 클러슽 후보군 생성하고
 4. 그래프 생성 
 5. 스타트 피니쉬
 6. 서치
 7. 이동 
 */

/**
 * @author neil
 * @class SeqTest
 * @brief console로 대체된 interface를 test한다.
 */
public class CopyOfSeqTest
{
	public static AgentGroup agentGroup;
	public static MapControl mapControl;
	private static NewHeuristicPathFinding finding;
	private ClusterControl CCInstance;
	private GraphControl graphControl;
	private int clusterNumX;
	private int clusterNumY;
	private int cellInCluster;

	public void dynamicTest(Point eventPoint)
	{
		// Mode에 알맞은 Event가 일어나야 한다.
		mapControl.getMap().dynamicMethod(eventPoint);

	}

	public CopyOfSeqTest()
	{
		CCInstance = ClusterControl.getInstance();
		graphControl = GraphControl.getInstance();
	}

	/**
	 * Map이 생성되고 난후 클러스터의 개수를 결정하고 클러스터를 구성하고 CSC 후보군을 구성하는 메소드
	 * 
	 * @param clusterNumX
	 *            => X * Y 으로 클러스터를 구성할 때 X 의값을 결정하는 Parameter
	 * @param clusterNumY
	 *            => X * Y 으로 클러스터를 구성할 때 Y 의값을 결정하는 Parameter
	 * @return 성공하면 True 실패하면 False
	 */
	public boolean createCluster(int clusterNumX, int clusterNumY)
	{

		this.clusterNumX = clusterNumX;
		this.clusterNumY = clusterNumY;

		if (CCInstance != null)
		{
			// System.out.println("New Clusters " + clusterNumX + " * " +
			// clusterNumY + " are made.");
			CCInstance.setNumX(clusterNumX);
			CCInstance.setNumY(clusterNumY);
			CCInstance.createCluster();
			CCInstance.createCandiCSC();
			return true;
		}
		else
		{
			System.err.println("CreateCluster is fail");
			return false;
		}
	}

	/**
	 * 클러스터에 대해서 후보군이 결정되어 졌으면 그래프를 구성하는 메소드
	 * 
	 * @return 성공하면 True 실패하면 False
	 */
	public boolean createGraph()
	{
		ClusterSearch clusterSearch = new ClusterSearch();
		if (clusterSearch != null)
		{
			clusterSearch.partialSearch();
			return true;
		}
		else
		{
			System.err.println("Create Graph is fail");
			return false;
		}
	}

	/**
	 * 스타트와 결과점 부분을 그래프와 연결시킨다.
	 * 
	 * @return
	 */
	public boolean sfConnectToGraph()
	{
		// Start와 Finish의 그래프를 있는다 .
		if (graphControl != null)
		{
			graphControl.connectSFGraph();
			return true;
		}
		else
		{
			System.err.println("Create Graph is fail");
			return false;
		}
	}

	/**
	 * 그래프가 다 구성되어 지고 난 후에 그래프 서치를 통해서 길을 찾는 메소드
	 * 
	 * @return 길을 못찾으면 1 길을 찾으면 0 에러 발생시 -1
	 */
	public int graphSearch()
	{
		graphControl.clearGraphParent();
		graphControl.findGraph();
		return 0;
	}

	/**
	 * 시작위치와 목표 위치를 정하는 method
	 */
	public void setSFPosition(Point start, Point finish)
	{
		Cell cell[][] = mapControl.getCellArray();

		CellControl.setStartCell(cell[start.x][start.y]);
		ClusterControl.getInstance().setStartCluster(start.x / cellInCluster,
				start.y / cellInCluster);

		CellControl.setFinishCell(cell[finish.x][finish.y]);
		ClusterControl.getInstance().setFinishCluster(finish.x / cellInCluster,
				finish.y / cellInCluster);

	}

	/**
	 * finding Thread를 get 하는 method
	 * 
	 * @return
	 */
	public static NewHeuristicPathFinding getFinding()
	{
		return finding;
	}

	/**
	 * 그래프 서치를 통해서 경로가 결정되어지면 길을 따라 이동하는 메소드
	 */

	public void move()
	{
		finding = NewHeuristicPathFinding.getInstance();
		finding.startSearch();
	}

	/**
	 * 맵에 포함된 셀에 대해서 장애물을 설정해주는 메소드
	 * 
	 * @param x
	 * @param y
	 * @param mode
	 */
	public void setBlock(int x, int y, int mode)
	{
		// Mode의 종류
		// MapControl.SET_OBSTACLES : 지나갈수 없는 장애물
		// MapControl.SET_HARD : 지나갈수는 있으나 가중치가 높은 장애물
		// MapControl.SET_NORMAL : 일반적인 길

		mapControl.getMap().setObstacle(x, y, mode);

	}

	/**
	 * 맵에 포함된 셀에 대해서 적을 설정해주는 메소드
	 * 
	 * @param x
	 * @param y
	 */
	public void setThreaten(int x, int y)
	{
		mapControl.getMap().setThreatn(x, y);
	}

	public static void main(String[] args)
	{
		int mapY = 200;
		int mapX = 200;

		CopyOfSeqTest test = new CopyOfSeqTest();
		
		/*Agent Group에 포함될 Agent의 Type을 정의 */
		String[] agentTypes= { "leader", "leftFront" };

		agentGroup = new AgentGroup(new Point(0, 0), agentTypes);

			//

		Random random = new Random(System.currentTimeMillis());
		for (int i = 0; i < AgentGroup.MAX_NUM_OF_AGENT; i++)
		{
			
			agentGroup.addAgentIntoGroup(new Agent(agentGroup.createID(), AgentGroup.AgentType
					.nextElement().toString(), new Point(agentGroup.getCurrentPosion().x
					+ random.nextInt(10) * agentGroup.DEF_DIST_BET_AGENTS, random.nextInt(10)
					* agentGroup.DEF_DIST_BET_AGENTS)));
		
			System.out.println(agentGroup.getAgentByID("agent" + i).getID() + ":"
					+ agentGroup.getAgentByID("agent" + i).getAgentType());
		}

		ArrayList<Point> list = new ArrayList<Point>();
		for (int i = 0; i < 10; i++)
		{
			list.add(new Point(i, i + 10));
		}

		// agentGroup.setGroupPath(list);

		// agentGroup.getAgentAt("agent" + 3).setDead();

		mapControl = MapControl.getInstance();
		mapControl.createMap(mapX, mapY);
		mapControl.setLevel(1);

		// 블록 부분은 클러스터가 생성되기전에 넣어야 합니다.
//		test.setBlock(7, 7, MapControl.SET_OBSTACLES);
//		test.setBlock(17, 7, MapControl.SET_OBSTACLES);
//		test.setBlock(7, 57, MapControl.SET_OBSTACLES);

		test.createCluster(4, 4);
		test.cellInCluster = mapX / test.clusterNumX;

		test.createGraph();
		test.setSFPosition(agentGroup.getCurrentPosion(), new Point(100, 167));
		test.sfConnectToGraph();
		test.graphSearch();
		test.move();

		Vector<Cell> path = NewHeuristicPathFinding.getPathList();

		// System.out.println(path.size());
		// for (int i = 0; i < path.size(); i++)
		// {
		// System.out.println(path.get(i));
		// }

		// Vector<Cell> a = GraphControl.getInstance().getGoalList();
		// for(Iterator<Cell> i = a.iterator();i.hasNext();){
		// System.err.println(i.next().getPosition());
		// }
		//

		System.err.println("Success");
		/*
		 * sequence 1. normal test 2. CSC test 3. dynamic test 4. hiding 5. set
		 * NPC intelligence level 6. Multi agent
		 */

		for (int i = 0; i < agentGroup.getAgentList().size(); i++)
		{
			agentGroup.getAgentByID("agent" + i).getAgentThread().start();
			// agentGroup.getAgentByID("agent" +
			// i).setAgentPath(AgentGroup.groupPath);
		}
		// agentGroup.moveGroup();

	}
}
